package cn.ciis.sys.permission;

import cn.ciis.basic.base.BaseController;
import cn.ciis.basic.base.BaseService;
import cn.ciis.basic.model.Account;
import cn.ciis.basic.model.Permission;
import com.jfinal.core.Action;
import com.jfinal.core.JFinal;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;

import java.lang.reflect.Method;
import java.util.*;

/**
 * 权限管理业务
 *
 * @author 冉志林
 */
public class PermissionAdminService extends BaseService {

    private Permission dao = new Permission().dao();

    @Override
    public Model getDao() {
        return dao;
    }

    public Ret delete(String ids) {
        Db.delete("delete from sys_role_permission where permissionId in(" + ids + ")");
        return Db.delete("delete from sys_permission where id in(" + ids + ")") > 0
                ? success()
                : fail();
    }

    // 用于排除掉 BaseController 中的几个成为了 action 的方法
    private Set<String> excludedMethodName = buildExcludedMethodName();

    /**
     * 升级到 jfinal 3.5 以后，将 BaseController 中的 @Before(NotAction.class) 改成 @NotAction 以后，可以删除本方法
     */
    private Set<String> buildExcludedMethodName() {
        Set<String> excludedMethodName = new HashSet<String>();
        Method[] methods = BaseController.class.getMethods();
        for (Method m : methods) {
            if (m.getParameterTypes().length == 0) {
                excludedMethodName.add(m.getName());
            }
        }
        return excludedMethodName;
    }



    /**
     * 同步 permission 获取后台管理所有 actionKey 以及 controller，将数据自动写入 permission 表 随着开发过程的前行，可以动态进行同步添加新的
     * permission 数据
     */
    public Ret sync() {
        int counter = 0;
        List<String> allActionKeys = JFinal.me().getAllActionKeys();
        List<Record> taxonomys = Db.find("SELECT * FROM `sys_taxonomy` WHERE isEnable=1");
        for (Record taxonomy : taxonomys) {
            for (String actionKey : allActionKeys) {
                // 只处理后台管理 action，其它跳过
                if (!actionKey.startsWith("/admin")) {
                    continue;
                }
                String tax = "/admin/" + taxonomy.getStr("identification");
                if (!actionKey.startsWith("/admin/sys")
                        && !actionKey.startsWith(tax)
                        && !"/admin".equals(actionKey)) {
                    continue;
                }
                String[] urlPara = new String[1];
                Action action = JFinal.me().getAction(actionKey, urlPara);
                if (action == null || excludedMethodName.contains(action.getMethodName())) {
                    continue;
                }

                String controller = action.getControllerClass().getName();

                String sql = "select * from sys_permission where actionKey=? and controller = ? limit 1";
                Permission permission = dao.findFirst(sql, actionKey, controller);

                String setNotes = setNotes(action);
                if (StrKit.notNull(setNotes)) {
                    List<Record> find =
                            Db.find("select * from sys_action_notes where actionKey=?", controller);
                    if (find.isEmpty()) {
                        Db.save(
                                "sys_action_notes",
                                new Record().set("actionKey", controller).set("notes", setNotes));
                    } else {
                        Db.update(
                                "update sys_action_notes set notes=? where actionKey=?", setNotes, controller);
                    }
                }

                if (permission == null) {
                    permission = new Permission();
                    permission.setActionKey(actionKey);
                    permission.setController(controller);
                    setRemarkValue(permission, action);
                    if (StrKit.notBlank(permission.getRemark())) {
                        // 存在remark注解
                        permission.save();
                    }
                    counter++;
                } else {
                    // 如果 remark 字段是空值，才去尝试使用 @Remark 注解中的值
                    if (StrKit.isBlank(permission.getRemark())) {
                        setRemarkValue(permission, action);
                        if (permission.update()) {
                            counter++;
                        }
                    }
                }
            }
        }

        int i = deleteAction();
        if (counter == 0) {
            if (i > 0) {
                return Ret.ok("msg", "权限已经是最新状态，无需更新,删除过期的" + i + "条数据");
            } else {
                return Ret.ok("msg", "权限已经是最新状态，无需更新");
            }
        } else {
            if (i > 0) {
                return Ret.ok("msg", "权限更新成功，共更新权限数 : " + counter + ",删除过期的" + i + "条数据");
            } else {
                return Ret.ok("msg", "权限更新成功，共更新权限数 : " + counter);
            }
        }
    }

    private String setNotes(Action action) {
        Notes notes = action.getMethod().getAnnotation(Notes.class);
        if (notes != null && StrKit.notBlank(notes.value())) {
            return notes.value();
        }
        return null;
    }

    public int deleteAction() {
        int i = 0;
        for (Permission p : dao.findAll()) {
            String actionKey = p.getActionKey();
            if ("/admin".equals(actionKey)) {
                continue;
            }
            String[] urlPara = new String[1];
            Action action = JFinal.me().getAction(actionKey, urlPara);
            if (action == null || !actionKey.equals(action.getActionKey())) {
                int b = deltePk("actionKey", actionKey);
                if (b > 0) {
                    i++;
                }
            }
        }
        return i;
    }

    private void setRemarkValue(Permission permission, Action action) {
        cn.ciis.sys.permission.Remark remark = action.getMethod().getAnnotation(cn.ciis.sys.permission.Remark.class);
        if (remark != null && StrKit.notBlank(remark.value())) {
            permission.setRemark(remark.value());
        }
    }

    public List<Permission> getAllPermissions(String roleId) {
        if (StrKit.isBlank(roleId)) {
            return dao.find("select * from sys_permission order by controller asc");
        } else {
            return dao.find(
                    "select a.* from sys_permission a INNER JOIN sys_role_permission b ON a.id=b.permissionId AND roleId=? order by controller asc",
                    roleId);
        }
    }


    /**
     * 查询传入账号拥有的权限
     * @param account
     * @return
     */
    public Map<String, Permission> findMyPermission(Account account){

        List<Record> accountRoles = Db.find("SELECT t1.accountId,t1.roleId,t2.`name` FROM sys_account_role t1 LEFT JOIN sys_role t2 ON t1.roleId = t2.id WHERE t1.accountId= ?", account.getId());

        List<Permission> temp_permissions=null;
        Map<String, Permission> temp_map= new HashMap<String, Permission>();

        for (Record accountRole : accountRoles) {
            temp_permissions = getAllPermissions(accountRole.get("roleId").toString());

            temp_permissions.forEach(per->{
                if(temp_map.containsKey(per.getActionKey())) {
                   // temp_map.get(per.getActionKey()).put("deps", temp_map.get(per.getActionKey()).getStr("deps")+","+accountRole.getExt());
                }else {
                    //per.put("deps", accountRole.getExt());
                    temp_map.put(per.getActionKey(),per);
                }
            });

        }
        //设置默认权限
        Permission.setDefault(temp_map);
        return temp_map;
    }
}
